#include "JY931.h"
#include "BSP.h"
#include <string.h>

char UnLock[5] = {0xFF, 0xAA, 0x69, 0x88, 0xB5};    // 解锁
char SetAngle[5] = {0xFF, 0xAA, 0x01, 0x08, 0x00};  // 设置角度
char ACCCALSW[5] = {0xFF, 0xAA, 0x01, 0x01, 0x00};  // 进入加速度校准模式
char SAVACALSW[5] = {0xFF, 0xAA, 0x00, 0x00, 0x00}; // 保存当前配置

/* 时间 */
struct sTime_t
{
    unsigned char ucYear;
    unsigned char ucMonth;
    unsigned char ucDay;
    unsigned char ucHour;
    unsigned char ucMinute;
    unsigned char ucSecond;
    unsigned short usMiliSecond;
} STime;

/* 加速度 */
struct sAcc_t
{
    short a[3];
    short T;
} SAcc;

/* 角速度 */
struct sGyro_t
{
    short w[3];
    short T;
} SGyro;

/* 角度 */
struct sAngle_t
{
    short Angle[3];
    short T;
} SAngle;

/* 磁场 */
struct sMag_t
{
    short h[3];
    short T;
} SMag;

/* 端口状态 */
struct sDStatus_t
{
    short sDStatus[4];
} SDStatus;

/* 气压 */
struct sPress_t
{
    long lPressure;
    long lAltitude;
} SPress;

/* 经纬度 */
struct sLonLat_t
{
    long lLon;
    long lLat;
} SLonLat;

/* GPS */
struct sGPS_t
{
    short sGPSHeight;
    short sGPSYaw;
    long lGPSVelocity;
} SGPS;

/* 四元数 */
struct sQ_t
{
    short q[4];
} SQ;

uint8_t data[11];
uint8_t empty[5];

void JY931_Callback(uint8_t *pData, uint8_t size)
{
    // 如果数据包的帧头或帧尾错误需要重新校准
    if (pData[0] != 0x55)
    {
        HAL_UART_Receive(&JY931_UART, data, 11, 100);

        // 调整数据帧，使下一次串口接收的11个字节正确匹配数据帧
        for (uint8_t i = 0; i < 11; i++)
        {
            // 检测帧头的位置
            if (data[i] == 0x55)
            {
                HAL_UART_Receive(&JY931_UART, data, i, 100); // 根据错误帧头的位置调整数据包
                break;
            }
        }
    }
    else
    {
        switch (pData[1]) // 判断数据是哪种数据，然后将其拷贝到对应的结构体中，有些数据包需要通过上位机打开对应的输出后，才能接收到这个数据包的数据
        {
        case 0x50:
            memcpy(&STime, &pData[2], 8);
            break;
        case 0x51:
            memcpy(&SAcc, &pData[2], 8);
            break;
        case 0x52:
            memcpy(&SGyro, &pData[2], 8);
            break;
        case 0x53:
            memcpy(&SAngle, &pData[2], 8);
            break;
        case 0x54:
            memcpy(&SMag, &pData[2], 8);
            break;
        case 0x55:
            memcpy(&SDStatus, &pData[2], 8);
            break;
        case 0x56:
            memcpy(&SPress, &pData[2], 8);
            break;
        case 0x57:
            memcpy(&SLonLat, &pData[2], 8);
            break;
        case 0x58:
            memcpy(&SGPS, &pData[2], 8);
            break;
        case 0x59:
            memcpy(&SQ, &pData[2], 8);
            break;
        }
    }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart == &JY931_UART)
    {
        JY931_Callback(data, 11);

        HAL_UART_Receive_DMA(&JY931_UART, data, 11); // 开启DMA
    }
}

/* JY931传感器初始化 */
void JY931_Init(void)
{
    HAL_UART_Transmit(&JY931_UART, (uint8_t *)UnLock, 5, 100);
    HAL_Delay(100);
    HAL_UART_Transmit(&JY931_UART, (uint8_t *)SetAngle, 5, 100);
    HAL_Delay(100);
    HAL_UART_Transmit(&JY931_UART, (uint8_t *)ACCCALSW, 5, 100);
    HAL_Delay(100);
    HAL_UART_Transmit(&JY931_UART, (uint8_t *)SAVACALSW, 5, 100);
    HAL_Delay(100);

    HAL_UART_Receive(&JY931_UART, data, 11, 500);

    // 调整数据帧，使下一次串口接收的11个字节正确匹配数据帧
    for (uint8_t i = 0; i < 11; i++)
    {
        // 检测帧头的位置
        if (data[i] == 0x55)
        {
            HAL_UART_Receive(&JY931_UART, data, i, 500); // 根据错误帧头的位置调整数据包

            break;
        }
    }

    HAL_UART_Receive_DMA(&JY931_UART, data, 11); // 开启DMA
}

/* JY931获得角度 */
void JY931_GetAngle(void)
{
    JY931.roll = (float)SAngle.Angle[0] / 32768 * 180;
    JY931.pitch = (float)SAngle.Angle[1] / 32768 * 180;
    JY931.yaw = (float)SAngle.Angle[2] / 32768 * 180;
}
